package cn.gailvlun.gll.presentation.emotion.drawer;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.databinding.DataBindingUtil;
import android.databinding.ViewDataBinding;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityOptionsCompat;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;

import com.github.markzhai.recyclerview.BaseViewAdapter;
import com.github.markzhai.recyclerview.BindingViewHolder;
import com.haibin.calendarview.BaseView;
import com.haibin.calendarview.Calendar;
import com.haibin.calendarview.CalendarView;

import org.jetbrains.annotations.NotNull;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cn.gailvlun.gll.R;
import cn.gailvlun.gll.databinding.ActivityEmotionCalendarBinding;
import cn.gailvlun.gll.databinding.ItemEmotionCalendarDetailBinding;
import cn.gailvlun.gll.net.HttpMethods;
import cn.gailvlun.gll.net.HttpSubscriber;
import cn.gailvlun.gll.net.ListRes;
import cn.gailvlun.gll.net.emotion.Emotion;
import cn.gailvlun.gll.presentation.base.BaseActivity;
import cn.gailvlun.gll.presentation.emotion.EmotionDetail2Activity;
import cn.gailvlun.gll.presentation.emotion.bean.EmotionDetailTransfer;
import cn.gailvlun.gll.presentation.emotion.core.BaseAdapter;
import cn.gailvlun.gll.presentation.emotion.core.BaseViewModel;
import cn.gailvlun.gll.presentation.emotion.photo.GalleryActivity;
import cn.gailvlun.gll.presentation.emotion.util.EmotionDateUtil;
import cn.gailvlun.gll.presentation.emotion.util.Util;
import cn.gailvlun.gll.presentation.emotion.widget.CollapseTextView;
import cn.gailvlun.gll.presentation.emotion.widget.DividerDecoration;
import cn.gailvlun.gll.util.DialogUtil;
import cn.gailvlun.gll.util.IsEmpty;
import cn.gailvlun.gll.util.RxUtil;
import cn.gailvlun.gll.widget.ImageGroupView;
import cn.gailvlun.gll.widget.NavigationBarView;
import cn.gailvlun.gll.widget.statelayout.State;
import io.reactivex.functions.Consumer;
import rx_activity_result2.Result;
import rx_activity_result2.RxActivityResult;

import static cn.gailvlun.gll.presentation.emotion.core.BaseViewModelKt.RESULT_DELETE;
import static cn.gailvlun.gll.presentation.emotion.photo.GalleryFragmentKt.VIEW_NAME_IMAGE;


public class EmotionCalendarActivity extends BaseActivity {

    private ActivityEmotionCalendarBinding mBinding;
    private RecyclerView rvEmotionList;
    private BaseAdapter mAdapter;
    private Map<LocalDate, List<Emotion>> emotionMap = new HashMap<>();
    private LocalDate selectDate;
    private Presenter mViewModel;

    public static void openActivity(Context context, Consumer<Result<Activity>> consumer) {
        Intent i = new Intent(context, EmotionCalendarActivity.class);
        RxActivityResult.on((Activity) context)
                .startIntent(i)
                .subscribe(consumer);
    }

    @Override
    protected void initComponent() {
        mBinding = DataBindingUtil.setContentView(this, R.layout.activity_emotion_calendar);
        mAdapter = new EmotionCalendarAdapter(this);
        mViewModel = new Presenter(mContext, mAdapter);
        mAdapter.setPresenter(mViewModel);
        final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
        mAdapter.setDecorator(new BaseViewAdapter.Decorator() {
            @Override
            public void decorator(BindingViewHolder holder, final int position, int viewType) {
                final ViewDataBinding itemBinding = holder.getBinding();

                
                if (itemBinding instanceof ItemEmotionCalendarDetailBinding) {

                    ((ItemEmotionCalendarDetailBinding) itemBinding).llTextAndImage.igvEmotionImage.setOnPhotoClickListener(new ImageGroupView.OnPhotoClickListener() {
                        @Override
                        public void onItemClick(ImageView iv, List<String> photos, int position) {
                            ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(mContext, ((ItemEmotionCalendarDetailBinding) itemBinding).llTextAndImage.igvEmotionImage, VIEW_NAME_IMAGE + "-" + position);
                            GalleryActivity.Companion.openActivity(mContext, new ArrayList<>(photos), position, null);
                        }
                    });
                    final Emotion emotion = (Emotion) mAdapter.getData().get(position);
                    ((ItemEmotionCalendarDetailBinding) itemBinding).rlToolBar.ctvFunction.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            mViewModel.showFunction(view, emotion);
                        }
                    });
                    ((ItemEmotionCalendarDetailBinding) itemBinding).llTextAndImage.ctvContent.setOnCollapseTextListener(new CollapseTextView.OnCollapseTextListener() {
                        @Override
                        public void onCollapseText(View view) {
                            Rect r = new Rect();
                            mBinding.rvEmotionList.getChildVisibleRect(itemBinding.getRoot(), r, null);
                            if (r.top < 20) {
                                linearLayoutManager.scrollToPositionWithOffset(position, mBinding.navigationBar.getHeight());
                            }
                        }
                    });
                }
            }
        });
        mBinding.setPresenter(mViewModel);
        rvEmotionList = findViewById(R.id.rvEmotionList);
        rvEmotionList.setAdapter(mAdapter);
        rvEmotionList.setLayoutManager(linearLayoutManager);
        rvEmotionList.addItemDecoration(new DividerDecoration(this));
    }


    @Override
    protected void createHandler() {
        mBinding.navigationBar.setOnBackListener(new NavigationBarView.OnBackListener() {
            @Override
            public void onBack(NavigationBarView nb) {
                onBackPressed();
            }
        });
        mBinding.calendarView.setDrawableProvider(new BaseView.DrawableProvider() {
            @Override
            public Drawable getDrawable(Calendar calendar) {
                String date = calendar.getYear() + "/" + calendar.getMonth() + "/" + calendar.getDay();
                LocalDate localDate = LocalDate.parse(date, DateTimeFormat.forPattern("yyyy/MM/dd"));
                if (emotionMap != null) {
                    List<Emotion> emotionList = emotionMap.get(localDate);
                    if (emotionList != null && !emotionList.isEmpty()) {
                        return Util.get10KindsEmotionMiddleIcon(emotionList.get(0).getEmotion());
                    }
                }
                return null;
            }
        });
        mBinding.calendarView.setOnDateSelectedListener(new CalendarView.OnDateSelectedListener() {
            @Override
            public void onDateSelected(Calendar calendar, boolean isClick) {
                mBinding.tvCalendarTitle.setText(EmotionDateUtil.getCalendarTitle(calendar));
                selectDate = EmotionDateUtil.dateFormat(calendar.getYear(), calendar.getMonth(), calendar.getDay());
                updateList(selectDate);
                if (!IsEmpty.list(emotionMap.get(selectDate))) {
                    mBinding.stateLayout.show(State.LOADING);
                    getSingleDayEmotion(selectDate);
                }
            }
        });
    }

    @Override
    protected void loadData(@Nullable Bundle savedInstanceState) {
        selectDate = LocalDate.now();
        
        getEmotion(LocalDate.parse(selectDate.toString("yyyy-MM-01")), selectDate);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (mViewModel.getFunctionPopupWindow().isShowing()) {
            mViewModel.getFunctionPopupWindow().dismiss();
            return true;
        } else {

            return super.dispatchTouchEvent(ev);
        }
    }

    private void getSingleDayEmotion(final LocalDate localDate) {
        
        long selectStartMills = selectDate.toDateTimeAtStartOfDay().getMillis() / 1000;
        
        long selectEndMills = selectDate.toDateTimeAtStartOfDay().plusDays(1).getMillis() / 1000;

        HttpMethods.getEmotionService()
                .emotionListP(selectStartMills, selectEndMills, null, "all")
                .compose(RxUtil.<ListRes<Emotion>>applyScheduler())
                .subscribe(new HttpSubscriber<ListRes<Emotion>>() {
                    @Override
                    protected void onSuccess(ListRes<Emotion> response) {
                        int n = response.getResults().size();
                        
                        if (emotionMap.get(localDate) != null) {
                            emotionMap.get(localDate).clear();
                        }
                        for (int i = 0; i < n; ++i) {
                            Emotion e = response.getResults().get(i);
                            LocalDate date = EmotionDateUtil.dateFormat(e.getCreated());
                            List<Emotion> cacheEmotionListByDate = emotionMap.get(date);
                            if (cacheEmotionListByDate == null) {
                                cacheEmotionListByDate = new ArrayList<>();
                                emotionMap.put(date, cacheEmotionListByDate);
                            }
                            cacheEmotionListByDate.add(e);
                        }
                        mBinding.calendarView.notifyPage();
                        updateList(selectDate);
                    }

                    @Override
                    protected void onFailure(String errMsg, @Nullable ListRes<Emotion> response, int code) {
                        DialogUtil.showError(mContext, errMsg);
                    }

                    @Override
                    protected void onFinish() {
                        super.onFinish();

                        mBinding.stateLayout.show(State.CONTENT);
                    }
                });
    }

    private void getEmotion(final LocalDate startDate, LocalDate endDate) {
        
        long startMills = startDate.toDateTimeAtStartOfDay().getMillis() / 1000;
        
        long endMills = endDate.plusDays(1).toDateTimeAtStartOfDay().getMillis() / 1000;

        mBinding.stateLayout.show(State.LOADING);
        HttpMethods.getEmotionService()
                .emotionListP(startMills, endMills, 31, "true")
                .compose(RxUtil.<ListRes<Emotion>>applyScheduler())
                .subscribe(new HttpSubscriber<ListRes<Emotion>>() {
                    @Override
                    protected void onSuccess(ListRes<Emotion> response) {
                        int n = response.getCount();
                        emotionMap.clear();
                        for (int i = 0; i < n; ++i) {
                            Emotion e = response.getResults().get(i);
                            LocalDate date = EmotionDateUtil.dateFormat(e.getCreated());
                            List<Emotion> cacheEmotionListByDate = emotionMap.get(date);
                            if (cacheEmotionListByDate == null) {
                                cacheEmotionListByDate = new ArrayList<>();
                                emotionMap.put(date, cacheEmotionListByDate);
                            }
                            cacheEmotionListByDate.add(e);
                        }
                        mBinding.calendarView.notifyPage();
                        updateList(selectDate);

                        if (!IsEmpty.list(emotionMap.get(selectDate))) {
                            getSingleDayEmotion(selectDate);
                        } else {
                            mBinding.stateLayout.show(State.CONTENT);
                        }
                    }

                    @Override
                    protected void onFailure(String errMsg, @Nullable ListRes<Emotion> response, int code) {
                        DialogUtil.showError(mContext, errMsg);

                        mBinding.stateLayout.show(State.CONTENT);
                    }
                });
    }

    
    private void updateList(LocalDate date) {
        if (emotionMap != null) {
            List<Emotion> emotionList = emotionMap.get(date);
            if (IsEmpty.list(emotionList)) {
                mAdapter.clear();
                mAdapter.add(null, EmotionCalendarAdapter.Type.EMPTY.ordinal());
            } else {
                mAdapter.set(emotionList, EmotionCalendarAdapter.Type.CONTENT.ordinal());
            }
        }
    }


    public class Presenter extends BaseViewModel {
        private View mParentView;

        public Presenter(@NotNull BaseActivity mActivity, @NotNull BaseAdapter mAdapter) {
            super(mActivity, mAdapter);
            mParentView = getLayoutInflater().inflate(R.layout.activity_emotion_calendar, null);
            initPopWindow(mParentView);
        }

        public void nextDate() {
            mBinding.calendarView.scrollToNext();
        }

        public void prevDate() {
            mBinding.calendarView.scrollToPre();
        }

        public String getDay() {
            return String.valueOf(selectDate.getDayOfMonth());
        }


        public void toDetail(Emotion e) {
            EmotionDetailTransfer transfer = new EmotionDetailTransfer();
            transfer.setId(e.getId());
            transfer.setFrom(EmotionCalendarActivity.class);
            transfer.setTitle(R.string.emotion_my_emotion);
            EmotionDetail2Activity.openActivity(EmotionCalendarActivity.this, transfer, new Consumer<Result<BaseActivity>>() {
                @Override
                public void accept(Result<BaseActivity> baseActivityResult) throws Exception {
                    if (RESULT_DELETE == baseActivityResult.resultCode()) {
                        deleteEmotionCallback();
                    }
                }
            });
        }


        public void showFunction(View anchor, Emotion emotion) {
            super.baseShowFunction(anchor, emotion);
        }

        public void deleteEmotionCallback() {
            getSingleDayEmotion(selectDate);
            setResult(RESULT_DELETE);
        }

        public void showOperateEmotionWindow(View view,Emotion emotion) {
            super.baseShowOperateEmotionWindow(mParentView, emotion);
        }

    }
}
